package com.guqin.interview.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.guqin.interview.model.entity.Question;
import com.guqin.interview.model.entity.User;
import com.guqin.interview.model.vo.QuestionVO;
import com.guqin.interview.service.QuestionRecommendService;
import com.guqin.interview.service.QuestionService;
import com.guqin.interview.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 题目推荐服务实现
 */
@Service
public class QuestionRecommendServiceImpl implements QuestionRecommendService {

    @Resource
    private UserService userService;

    @Resource
    private QuestionService questionService;

    @Override
    public List<QuestionVO> recommendQuestionsByUserTags(Long userId, int limit) {
        // 1. 获取用户信息
        User user = userService.getById(userId);
        if (user == null || user.getUserTags() == null) {
            return Collections.emptyList();
        }

        // 2. 获取用户标签
        JSONArray userTagsArray = JSONUtil.parseArray(user.getUserTags());
        List<String> userTags = userTagsArray.toList(String.class);
        if (userTags.isEmpty()) {
            return Collections.emptyList();
        }

        // 3. 获取所有题目
        List<Question> allQuestions = questionService.list();
        if (allQuestions.isEmpty()) {
            return Collections.emptyList();
        }

        // 4. 计算每个题目与用户标签的相似度
        Map<Question, Double> questionSimilarityMap = new HashMap<>();
        for (Question question : allQuestions) {
            JSONArray questionTagsArray = JSONUtil.parseArray(question.getTags());
            List<String> questionTags = questionTagsArray.toList(String.class);
            double similarity = calculateCosineSimilarity(userTags, questionTags);
            questionSimilarityMap.put(question, similarity);
        }

        // 5. 按相似度排序并返回前limit个题目
        return questionSimilarityMap.entrySet().stream()
                .sorted(Map.Entry.<Question, Double>comparingByValue().reversed())
                .limit(limit)
                .map(Map.Entry::getKey)
                .map(questionService::getQuestionVO)
                .collect(Collectors.toList());
    }

    @Override
    public double calculateCosineSimilarity(List<String> tags1, List<String> tags2) {
        if (tags1.isEmpty() || tags2.isEmpty()) {
            return 0.0;
        }

        // 1. 构建标签频率向量
        Map<String, Integer> vector1 = new HashMap<>();
        Map<String, Integer> vector2 = new HashMap<>();

        // 统计tags1中每个标签的频率
        for (String tag : tags1) {
            vector1.merge(tag, 1, Integer::sum);
        }

        // 统计tags2中每个标签的频率
        for (String tag : tags2) {
            vector2.merge(tag, 1, Integer::sum);
        }

        // 2. 计算点积
        double dotProduct = 0.0;
        for (String tag : vector1.keySet()) {
            if (vector2.containsKey(tag)) {
                dotProduct += vector1.get(tag) * vector2.get(tag);
            }
        }

        // 3. 计算向量模长
        double norm1 = Math.sqrt(vector1.values().stream()
                .mapToDouble(v -> v * v)
                .sum());
        double norm2 = Math.sqrt(vector2.values().stream()
                .mapToDouble(v -> v * v)
                .sum());

        // 4. 计算余弦相似度
        if (norm1 == 0.0 || norm2 == 0.0) {
            return 0.0;
        }
        return dotProduct / (norm1 * norm2);
    }
} 